}
+/* @func int32 GPS_Math_WGS84_To_ICS_EN ******************************
+**
+** Convert WGS84 latitude and longitude to
+** Israeli old Grid Eastings and Northings
+** ( Israeli Cassini Soldner )
+**
+** @param [r] phi [double] WGS84 latitude (deg)
+** @param [r] lambda [double] WGS84 longitude (deg)
+** @param [w] E [double *] ICS easting (metres)
+** @param [w] N [double *] ICS northing (metres)
+**
+** @return [void]
+************************************************************************/
+
+int32 GPS_Math_WGS84_To_ICS_EN(double lat, double lon, double *E,
+ double *N)
+{
+ const double phi0 = 31.734090;
+ const double lambda0 = 35.212060;
+ const double E0 = 170251.0;
+ const double N0 = 1126868.0;
+ double phi, lambda, alt, a, b;
+
+ if (lat < 29.333) return 0;
+ if (lat > 33.28) return 0;
+ if (lon < 34.18) return 0;
+ if (lon > 37.67) return 0;
+
+ a = GPS_Ellipse[27].a;
+ b = a - (a / GPS_Ellipse[27].invf);
+
+ GPS_Math_WGS84_To_Known_Datum_M(lat, lon, 0, &phi, &lambda, &alt, 124);
+ GPS_Math_Swiss_LatLon_To_EN(phi, lambda, E, N, phi0, lambda0, E0, N0, a, b);
+
+ return 1;
+}
+
+
+/* @GPS_Math_ICS_EN_To_WGS84 *****************************************
+**
+** Convert WGS84 latitude and longitude to
+** Israeli Oldl Grid Eastings and Northings
+**
+** @param [r] E [double] ICS easting (metres)
+** @param [r] N [double] ICS northing (metres)
+** @param [w] lat [double *] WGS84 latitude (deg)
+** @param [w] lon [double *] WGS84 longitude (deg)
+**
+** @return [void]
+************************************************************************/
+void GPS_Math_ICS_EN_To_WGS84(double E, double N, double *lat, double *lon)
+{
+ const double phi0 = 31.734090;
+ const double lambda0 = 35.212060;
+ const double E0 = 170251.0;
+ const double N0 = 1126868.0;
+ double phi, lambda, alt, a, b;
+
+
+ a = GPS_Ellipse[27].a;
+ b = a - (a / GPS_Ellipse[27].invf);
+
+ GPS_Math_Swiss_EN_To_LatLon(E, N, &phi, &lambda, phi0, lambda0, E0, N0, a, b);
+ GPS_Math_Known_Datum_To_WGS84_M(phi, lambda, 0, lat, lon, &alt, 124);
+}
+
+
+
+
/* @func GPS_Math_EN_To_LatLon **************************************
**
** Convert Eastings and Northings to latitude and longitude
--- /dev/null
+/*
+ Naviguide Routes
+
+
+ Copyright (C) 2009 Erez Zuler
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA
+
+ */
+
+#include "defs.h"
+#include "csv_util.h"
+#include "jeeps/gpsmath.h"
+#include <ctype.h>
+#include <math.h>
+
+#define MYNAME "Naviguide"
+
+
+
+
+
+
+/************* Specific Naviguide data formats ****************/
+
+/* Naviguide file header */
+typedef struct {
+ gbuint16 nof_wp; /* Little endean format */
+ char pad1[6]; /* 0xff, 0xff, 0x01, 0x00, 0x06, 0x00 */
+ char signature[9]; /* cWaypoint */
+ char pad2[4]; /* 0x01, 0x00, 0x00, 0x00 */
+} ng_file_header_t;
+
+/* Naviguide waypoint/rout data */
+typedef struct{
+ char pad1[8]; /* 0xfe, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00 */
+ /* coordination are in old israeli grid */
+ gbuint32 East;
+ gbuint32 North;
+ char pad2[2]; /* 0x01, 0x01 */
+ gbuint32 Alt;
+ char CommentLength;
+} ng_wp_data_t;
+
+typedef struct{
+ char pad1[2]; /* 0x01, 0x80 */
+ gbuint16 next_wp;
+ char pad2[2]; /* 0x00, 0x00 */
+} ng_next_wp_t;
+
+typedef struct {
+ unsigned char chHeaderLen;
+ char strName[255];
+ ng_wp_data_t wp_data;
+} ng_wp_no_comment_t;
+
+
+/* Global variables */
+
+static gbfile *file_in, *file_out;
+static short_handle mkshort_handle;
+static gbuint16 nof_wp;
+static route_head *rte_head;
+static ng_file_header_t ng_file_header;
+static ng_wp_no_comment_t WPNC;
+static ng_next_wp_t ng_next_wp;
+static char strComment[101];
+
+/* Process options */
+/* wp - process only waypoints */
+/* rte - process as route */
+/* wprte - Process waypoints and route */
+static char *process = NULL;
+static char *reorder = NULL;
+static int process_rte = 1;
+static int reorder_wp = 0;
+
+static char temp_short_name[5];
+
+
+
+
+/* Forward declarations */
+static void ng_read_file_header(void);
+
+static
+arglist_t ng_args[] = {
+ {"output", &process, "'wp' - Create waypoint file , 'rte' - Create route file",
+ "rte", ARGTYPE_STRING, ARG_NOMINMAX},
+ {"reorder", &reorder, "'n' - Keep the existing wp name, 'y' - rename waypoints",
+ "n", ARGTYPE_STRING, ARG_NOMINMAX},
+
+ ARG_TERMINATOR
+};
+
+/*===================Utilities ==========================================*/
+
+static void
+ng_convert_datum(waypoint *wpt)
+{
+ double lat, lon, east, north, alt;
+
+ east = (double) WPNC.wp_data.East;
+ north = (double) WPNC.wp_data.North;
+ alt = (double) WPNC.wp_data.Alt;
+
+ GPS_Math_ICS_EN_To_WGS84(east, north, &lat, &lon);
+ wpt->latitude = lat;
+ wpt->longitude = lon;
+ wpt->altitude = alt;
+}
+
+
+
+/*=================== File read/write utilities ==========================================*/
+
+static void
+ng_fwrite_wp_data (char *s, char *d, ng_wp_data_t *wp_data, gbfile *f) {
+ int i;
+ char z[50];
+
+ memset (z, 0, 50);
+
+ i = (s == NULL) ? 0 : strlen (s);
+ gbfwrite (&i, 1, 1, f);
+ gbfwrite (s, 1, i, f);
+
+ gbfwrite (&wp_data->pad1[0], 8, 1, f);
+ gbfputint32 (wp_data->East, f);
+ gbfputint32 (wp_data->North, f);
+ gbfwrite (&wp_data->pad2[0], 2, 1, f);
+ gbfputint32 (wp_data->Alt, f);
+
+ i = (d == NULL) ? 0 : strlen (d);
+ gbfwrite (&i, 1, 1, f);
+ gbfwrite (d, 1, i, f);
+ gbfwrite (z, 44, 1, f);
+}
+
+static void
+ng_fwrite_next_wp (ng_next_wp_t *nwp, gbfile *f) {
+ gbfwrite (nwp->pad1, 2, 1, f);
+ gbfputint16 (nwp->next_wp, f);
+ gbfwrite (nwp->pad2, 2, 1, f);
+}
+
+static void
+ng_fread_wp_data (char *d, ng_wp_no_comment_t *wpnc, gbfile *f) {
+
+ int i;
+
+ gbfread (&wpnc->chHeaderLen ,sizeof (wpnc->chHeaderLen), 1, f);
+ gbfread (&wpnc->strName, wpnc->chHeaderLen, 1, f);
+ wpnc->strName[wpnc->chHeaderLen] = 0;
+
+
+ gbfread (&wpnc->wp_data, 8, 1, f);
+ wpnc->wp_data.East = gbfgetint32 (f);
+ wpnc->wp_data.North = gbfgetint32 (f);
+ gbfread (&wpnc->wp_data.pad2,2, 1, f);
+ wpnc->wp_data.Alt = gbfgetint32 (f);
+ gbfread (&wpnc->wp_data.CommentLength, 1, 1, f);
+ i = (int)wpnc->wp_data.CommentLength;
+
+
+ /* Read the comment field */
+ gbfread (d, i + 44, 1, f);
+
+}
+
+static void
+ng_fread_next_wp (ng_next_wp_t *nwp, gbfile *f) {
+ gbfread (&nwp->pad1, 2, 1, f);
+ nwp->next_wp = gbfgetint16 (f);
+ gbfread (&nwp->pad2, 2, 1, f);
+}
+
+/* =================== Write data functions ====================================*/
+
+static void
+ng_fill_header_default (void) {
+ ng_file_header_t default_header = {
+ 0x00,
+ {0xff, 0xff, 0x01, 0x00, 0x09, 0x00},
+ {'C', 'W', 'a', 'y', 'P', 'o', 'i', 'n', 't'},
+ {0x01, 0x00, 0x00, 0x00},
+ };
+
+ ng_file_header =default_header;
+
+}
+
+
+static void
+ng_fill_waypoint_default (void) {
+ ng_wp_data_t default_wp = {
+ {0xfe, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00},
+ 0,
+ 0,
+ {0x01, 0x01},
+ 0,
+ 0x00,
+
+ };
+
+ ng_next_wp_t default_ng_next_wp = {
+ {0x01, 0x80},
+ 0,
+ {0x00, 0x00},
+ };
+
+ WPNC.wp_data = default_wp;
+ ng_next_wp = default_ng_next_wp;
+}
+
+
+static void
+ng_waypt_rd (const waypoint * wpt) {
+ char * s = NULL;
+
+ char z[50];
+ double lat, lon;
+ static int current_wp_ix=0;
+
+ memset (z, 0, 50);
+ current_wp_ix++;
+ ng_fill_waypoint_default();
+
+ if (!GPS_Math_WGS84_To_ICS_EN(wpt->latitude, wpt->longitude, &lon, &lat)) {
+ fatal(MYNAME ": Waypoint %d is out of the israeli grid area", current_wp_ix);
+ }
+
+ WPNC.wp_data.North = (gbuint32)lat;
+ WPNC.wp_data.East = (gbuint32)lon;
+
+ if (reorder_wp) {
+ sprintf (temp_short_name, "A%03d", current_wp_ix);
+ s = temp_short_name;
+ }
+
+ else
+ s = wpt->shortname;
+
+ ng_fwrite_wp_data (s, wpt->description, &WPNC.wp_data, file_out);
+
+
+ /* if not Last WP, write the next one index */
+
+ if (nof_wp > current_wp_ix) {
+ ng_next_wp.next_wp = current_wp_ix + 1;
+
+ ng_fwrite_next_wp (&ng_next_wp, file_out);
+
+ }
+}
+
+static void
+header_write (void) {
+ ng_file_header.nof_wp = nof_wp;
+ gbfputint16 (nof_wp, file_out);
+ gbfwrite(&ng_file_header.pad1[0], 19, 1, file_out);
+
+}
+
+
+static void
+data_write (void) {
+ nof_wp = waypt_count();
+ if (nof_wp) {
+ header_write ();
+ waypt_disp_all(ng_waypt_rd);
+ }
+ else {
+ nof_wp = route_waypt_count();
+ if (nof_wp) {
+ header_write ();
+ route_disp_all(NULL, NULL, ng_waypt_rd);
+ }
+ }
+}
+
+
+static void
+wr_init(const char *fname) {
+ file_out = gbfopen_le(fname, "wb", MYNAME);
+ ng_fill_header_default ();
+ if (NULL != reorder)
+ if (!case_ignore_strcmp(reorder, "y")) {reorder_wp = 1;}
+
+}
+
+static void
+wr_deinit () {
+ gbfclose(file_out);
+
+
+}
+
+/*=========================== Read data functions ==================================*/
+
+static void
+rd_init(const char *fname)
+{
+ file_in = gbfopen_le(fname, "rb", MYNAME);
+
+ mkshort_handle = mkshort_new_handle();
+ ng_read_file_header();
+
+ if (NULL != process) {
+ if (!case_ignore_strcmp(process, "wp")) {process_rte = 0;}
+ if (!case_ignore_strcmp(process, "rte")) {process_rte = 1;}
+ }
+
+
+}
+
+static void
+rd_deinit(void)
+{
+ gbfclose(file_in);
+ file_in = NULL;
+ mkshort_del_handle(&mkshort_handle);
+}
+
+
+
+static void
+ng_read_file_header(void)
+{
+
+ nof_wp = gbfgetint16 (file_in);
+ gbfread (&ng_file_header.pad1[0], 19, 1, file_in);
+ ng_file_header.nof_wp = nof_wp;
+
+
+ if (strncmp ("CWayPoint", ng_file_header.signature, 9))
+ fatal ("\nInvalid Naviguide file format\n");
+
+
+}
+
+static void
+data_read(void)
+{
+ int n, i;
+ waypoint *wpt_tmp;
+
+ if (process_rte) {
+ rte_head = route_head_alloc();
+ rte_head->rte_waypt_ct = nof_wp;
+ route_add_head(rte_head);
+ }
+
+ for (n = 0; n < nof_wp; ++n) {
+
+ wpt_tmp = waypt_new ();
+
+ /* Read waypoint data */
+
+ ng_fread_wp_data (strComment, &WPNC, file_in);
+
+
+ if (n < nof_wp - 1) {
+ /*
+ gbfread (&ng_next_wp.pad1[0], 2, 1, file_in);
+ ng_next_wp.next_wp = gbfgetint16 (file_in);
+ gbfread (&ng_next_wp.pad2[0], 2, 1, file_in);
+ */
+ ng_fread_next_wp (&ng_next_wp, file_in);
+
+ }
+ /* Clear commas form the comment for CSV file commonality */
+ for (i = 0; i <strlen (strComment); ++i) {
+ if (strComment[i] == ',')
+ strComment[i] = ' ';
+ }
+
+ /* put the data in the waypoint structure */
+ ng_convert_datum(wpt_tmp);
+
+ wpt_tmp->shortname = xstrdup (WPNC.strName);
+ wpt_tmp->description = xstrdup (strComment);
+
+ if (process_rte)
+ route_add_wpt(rte_head, wpt_tmp);
+ else
+ waypt_add(wpt_tmp);
+ }
+} /* data_read */
+
+
+
+ff_vecs_t ng_vecs = {
+ ff_type_file,
+ FF_CAP_RW_WPT,
+ rd_init,
+ wr_init,
+ rd_deinit,
+ wr_deinit,
+ data_read,
+ data_write,
+ NULL,
+ ng_args,
+ //CET_CHARSET_ASCII, 0 /* CET-REVIEW */
+ CET_CHARSET_HEBREW, 0
+};